package com.ruoyi.central.controller.custom;

import com.ruoyi.central.controller.TopCentralOperationStationController;
import com.ruoyi.central.controller.TopCentralProcessStepRunController;
import com.ruoyi.central.controller.TopCentralTaskCmdRunController;
import com.ruoyi.central.controller.vo.AreaVo;
import com.ruoyi.central.controller.vo.ArtProcessRunVo;
import com.ruoyi.central.controller.vo.ProcessStepRunVo;
import com.ruoyi.central.controller.vo.TaskCmdRunVo;
import com.ruoyi.central.domain.*;
import com.ruoyi.central.enums.MaterialStatusEnum;
import com.ruoyi.central.service.*;
import com.ruoyi.central.service.custom.IManualOperationStationService;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.exception.base.service.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.bean.BeanValidators;
import com.ruoyi.common.utils.bean.EnumUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.Assert;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Validator;
import java.io.IOException;
import java.util.*;

/**
 * @Classname ManualOperationStationController
 * @Author: sunluquan
 * @Date: 2022/5/8 19:03
 * @Description TODO
 * 站位人工操作页面的数据接口对象
 */
@Controller
@RequestMapping("central/manualOperationStation")
public class ManualOperationStationController {

    private String prefix = "central/manualOperationStation";
    //操作站点-物料 业务对象
    @Autowired
    private ITopCentralOperationStationMaterialService operationStationMaterialService;

    @Autowired
    private ITopCentralMaterialService materialService;

    @Autowired
    private ITopCentralArtProcessRunService artProcessRunService;

    @Autowired
    private ITopCentralProcessStepRunService processStepRunService;

    @Autowired
    private ITopCentralTaskCmdRunService taskCmdRunService;

    @Autowired
    private IManualOperationStationService manualOperationStationService;

    @Autowired
    private ITopCentralOperationStationService operationStationService;

    @Autowired
    TopCentralProcessStepRunController processStepRunController;

    @Autowired
    private Validator validator;

    @Autowired
    private TopCentralTaskCmdRunController taskCmdRunController;

    @Autowired
    private TopCentralOperationStationController operationStationController;

    /**
     * 处理站位移动逻辑
     * @return
     */
    @GetMapping("/moveToOperationStation")
    public String moveToOperationStation(@Validated TaskCmdRunVo.Params params, ModelMap mmap) throws IOException {

        return taskCmdRunController.toTaskCmdRunTemplate(params,mmap);
    }
    /**
     * 获取自动操作工位
     * @return
     */
    @GetMapping("/getAutoOperationStationList")
    @ResponseBody
    public AjaxResult getAutoOperationStationList(){

        return operationStationController.getAutoOperationStationList();
    }

    /**
     * description to {@link TopCentralTaskCmdRunController} method toTaskCmdRunTemplate
     * @param taskCmdRunId
     * @param mmap
     * @return
     * @throws IOException
     */
    @GetMapping("/toTaskCmdRunTemplate/{taskCmdRunId}")
    public String toTaskCmdRunTemplate(@PathVariable("taskCmdRunId")Integer taskCmdRunId, ModelMap mmap) throws IOException {

        return taskCmdRunController.toTaskCmdRunTemplate(null,mmap);
    }
    /**
     * 初始化物料与操作工位的关系 以及 初始化 执行工艺、执行工序、执行指令。
     * 1.修改物料状态为 使用中
     * 2.新增 物料-操作工位绑定对象
     * 3.新增 执行工艺对象（默认为执行状态）
     * 4.新增 执行工序对象（默认第一个执行工序为执行中状态）
     * 5.新增 执行指令对象（如果第一道工序的第一条指令为手动类型，将其状态修改为执行中状态）
     * @param operationStation
     * @return
     */
    @PostMapping("/checkAndInit")
    @ResponseBody
    public AjaxResult checkAndInit(@RequestBody AreaVo.OperationStation operationStation )
    {
        //操作工位编号
        Integer operationStationId = operationStation.getId();
        //物料编号
        String materialNo = operationStation.getMaterialNo();

        TopCentralOperationStationMaterial operationStationMaterial = new TopCentralOperationStationMaterial();
        operationStationMaterial.setOperationStationId(operationStationId);
        operationStationMaterial.setMaterialId(materialNo);

        BeanValidators.validateWithException(validator,operationStationMaterial);

        manualOperationStationService.checkAndInit(operationStationMaterial);

        return AjaxResult.success();
    }
    /**
     * 1.检测物料状态 如果物料状态不为加工中  抛出异常
     * 2.根据当前站位编号查询 物料-站位表，判断物料-站位表中的数据的物料编号 是否与当前一致 不一致抛出异常
     * @param operationStation
     * @return
     */
    @GetMapping()
    public String index(AreaVo.OperationStation operationStation, ModelMap mmap){
        //操作工位编号
        Integer operationStationId = operationStation.getId();
        //物料编号
        String materialNo = operationStation.getMaterialNo();

        TopCentralMaterial material = materialService.selectUsableById(materialNo);
        Assert.notNull(material,StringUtils.format("当前物料编号：{}不存在或状态为不可用！",materialNo));

        Integer materialStatus = material.getMaterialStatus();

        Integer artProcessId = material.getArtProcessId();
        //物料状态不为加工中的 都需要抛出异常
        if(!EnumUtils.equals(MaterialStatusEnum.USE_OF_STATUS,materialStatus)){
            //当前物料已经使用完成  不能再次操作
            if(EnumUtils.equals(MaterialStatusEnum.FINISHED_OF_STATUS,materialStatus)){

                throw new ServiceException("物料编号:{} 加工状态为：{} 不能在进行加工！",materialNo,MaterialStatusEnum.FINISHED_OF_STATUS.getDescription());

            }
            if(EnumUtils.equals(MaterialStatusEnum.FREE_OF_STATUS,materialStatus)){

                throw new ServiceException("物料编号:{} 加工状态为：{} 请先进行初始化！",materialNo,MaterialStatusEnum.FREE_OF_STATUS.getDescription());

            }

            throw new ServiceException("物料编号:{} 状态异常，请联系管理员！",materialNo);

        }

        //获取工位现在绑定的加工物料
        TopCentralOperationStationMaterial operationStationMaterial = operationStationMaterialService.selectByOperationStationId(operationStationId);
        //如果工位绑定的加工物料与当前不符  则抛出异常
        if(!StringUtils.equals(operationStationMaterial.getMaterialId(),materialNo)){

            throw new ServiceException("物料编号:{} 与当前加工站位绑定的物料编号不符 ！",materialNo,MaterialStatusEnum.FINISHED_OF_STATUS.getDescription());

        }

        TopCentralArtProcessRun artProcessRunOfParams = new TopCentralArtProcessRun();

        artProcessRunOfParams.setArtProcessId(artProcessId);
        artProcessRunOfParams.setProdId(material.getId());
        TopCentralArtProcessRun artProcessRun = artProcessRunService.selectOne(artProcessRunOfParams);

        Assert.notNull(artProcessRun,StringUtils.format("当前物料编号：{} 绑定工艺不存在或状态为不可用！",materialNo));

        TopCentralOperationStation materialBindingOperationStation = operationStationService.selectAllMap().get(operationStationId);

        Assert.notNull(artProcessRun,StringUtils.format("当前物料编号：{} 绑定操作工位不存在或状态为不可用！",materialNo));

        material.setOperationStation(materialBindingOperationStation);
        material.setArtProcessRun(artProcessRun);

        mmap.put("material",material);
        mmap.put("data","<th:block th:include=\"central/include :: footer\" /> const operationTypeDataList1 = [[${@dict.getType('central_operation_type')}]]");
        return prefix+"/manualOperationStation";
    }


    /**
     * 获取执行工艺编号下的所有执行工序时间线
     * @param artProcessRunId
     * @return
     */
    @GetMapping("/getTimeLineByArtProcessRunId/{artProcessRunId}")
    @ResponseBody
    public AjaxResult getTimeLineByArtProcessRunId(@PathVariable("artProcessRunId") Integer artProcessRunId){

        return processStepRunController.getTimeLineByArtProcessRunId(artProcessRunId);
    }
    /**
     * 获取最新的实时工序执行数据
     * @return
     */
    @GetMapping("/getReaTimeProcessStepList")
    @ResponseBody
    public AjaxResult getReaTimeProcessStepList(@Validated ArtProcessRunVo artProcessRunVo){
        //工艺执行编号
        Integer artProcessRunId = artProcessRunVo.getArtProcessRunId();

        TopCentralProcessStepRun processStepRunOfParams = BeanUtils.initialize(TopCentralProcessStepRun.class,
               item->item.setArtProcessRunId(artProcessRunId));
        //获取工艺执行 下 所有的工序执行列表
        List<TopCentralProcessStepRun> processStepRuns = processStepRunService.selectSimpleList(processStepRunOfParams);

//        if(StringUtils.isNotEmpty(processStepRuns)){
//            //获取活跃的执行工序任务
//            TopCentralProcessStepRun activeProcessStepRun = CollectionUtils.find(processStepRuns,
//                    processStepRun -> TaskStatusEnum.isActive(processStepRun.getTaskStatus())
//            );
//            if(activeProcessStepRun!=null){
//                //根据活跃的执行工序任务对象  获取 当前执行工序下的所有 任务执行指令列表
//                Integer activeProcessStepRunId = activeProcessStepRun.getId();
//
//                List<TopCentralTaskCmdRun> taskCmdRunsOfActiveProcessStepRun = taskCmdRunService.selectByProcessStepRunId(activeProcessStepRunId);
//                //将执行指令列表填充 至 执行工序中
//                activeProcessStepRun.setTaskCmdRuns(taskCmdRunsOfActiveProcessStepRun);
//            }
//
//        }

        return AjaxResult.success(processStepRuns);

    }

    /**
     * 根据可以行工序编号获取 执行工序编号下的 可执行任务指令列表
     * @param processStepRunId 执行工序编号
     * @return
     */
    @GetMapping("/getTaskCmdRunListByProcessStepRunId/{processStepRunId}")
    @ResponseBody
    public AjaxResult getTaskCmdRunListByActiveProcessStepId(@PathVariable("processStepRunId")Integer processStepRunId){

        List<TopCentralTaskCmdRun> taskCmdRuns = taskCmdRunService.selectByProcessStepRunId(processStepRunId);

        return AjaxResult.success(taskCmdRuns);
    }

    /**
     * 处理 执行任务指令 对象
     * @param taskCmdRun
     * @return
     */
    @PostMapping("/handleTaskCmdRun")
    @ResponseBody
    public AjaxResult handleTaskCmdRun(@RequestBody @Validated TopCentralTaskCmdRun taskCmdRun){

        if(taskCmdRunService.handleTaskCmdRun(taskCmdRun)){
            return AjaxResult.success();
        }else{
            return AjaxResult.error();
        }
    }

    /**
     * 完成工序执行
     *  1.修改当前执行工序为完成
     *  2.如果当前执行工序不是最后一道工序 进入 2.1 否则进入2.2
     *
     *  2.1修改下一道工序为开始执行
     *  2.1-1判断下一道工序是否有执行指令，且执行指令第一个操作类型为 手动 就进入 2.1-2
     *  1.2-2修改第一道执行指令为开始执行
     *
     *  2.2修改当前工序的工艺执行对象 为完成
     *  2.2.1删除 物料-操作工位绑定对象
     *  2.2.2修改物料对象的 物料状态为 已加工完成
     * @param processStepRunVo 活跃得工序执行对象
     */
    @RequiresPermissions("central:centralProcessStepRun:update")
    @PostMapping("/toCompleteProcess")
    @ResponseBody
    public AjaxResult toCompleteProcess(@RequestBody @Validated ProcessStepRunVo processStepRunVo){

        TopCentralArtProcessRun artProcessRun = manualOperationStationService.toCompleteProcess(processStepRunVo);

        return AjaxResult.success(artProcessRun);
    }
}
